前一篇我們測試簡單元件上的屬性,今天用component搭配service一起做個簡單的測試
今日學習目標以理解如何測試service為主,所以延續前一個 UserComponent.html
UI,這次我們增加isLoggedIn
的變數,以及新增一個service,稍微調整component,然後在寫spec測試寫的內容有沒有符合預期。
isLoggedIn
和 !isLoggedIn
來測試登入和未登入狀態<div *ngIf="isLoggedIn">
<h1>User logged in</h1>
<p>User is: {{ user.name }}</p>
</div>
<div *ngIf="!isLoggedIn">
<h1>User not logged in</h1>
<p>Please log in first</p>
</div>
ng g s user
,然後只寫一個user的物件,可以從外部取得nameline 18
export class UserComponent implements OnInit {
user: {name: string} = { name: ''};
isLoggedIn = false;
constructor(private userService: UserService) { }
ngOnInit(): void {
this.user = this.userService.user;
}
}
line 2, line 3
建立與取得測試用元件UserComponent
,取得元件後,從 fixture 透過injector取得 UserService
,因為DOM會動態更新,避免測試瀏覽器在run的時候,拿到undefined的變數 user.name
,所以要加上 line 9
去偵測更新DOM。最後line 10
預期userService的user name == UserComponent上的user nameit('should use the user name from the service', () => {
let fixture = TestBed.createComponent(UserComponent);
let component = fixture.componentInstance;
// 這行是重點!!
let userService = fixture.debugElement.injector.get(UserService);
// 避免拿到undefined的property
fixture.detectChanges();
expect(userService.user.name).toEqual(component.user.name);
});
這次要測試用isLoggedIn的變數,假設登入狀況,所以 line 2, line 3
建立與取得元件後,設定UserComponent的isLoggedIn為true,也就是 line 5
,一樣避免在環境還沒run完全之前拿到undefined的變數,需要偵測DOM的狀態,加入 line 7
,那接著宣告一個變數compiled
來取得DOM上面的元素,最後看元素的內容有沒有元件裡名字。
it('should display the user name if user is logged in', () => {
let fixture = TestBed.createComponent(UserComponent);
let app = fixture.componentInstance;
// 測試登入情境
app.isLoggedIn = true;
fixture.detectChanges();
let compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('p').textContent).toContain(app.user.name)
});
有登入成功的測試情境,反之就有「未登入」的情境,這次把isLoggedIn
拿掉,應該就會測試成功了吧?!
it('should\'t display the user name if user is not logged in', () => {
let fixture = TestBed.createComponent(UserComponent);
let app = fixture.componentInstance;
fixture.detectChanges();
let compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('p').textContent).toContain(app.user.name)
});
看看上面寫的Expected 'Please log in first' to contain 'Chris'.
,因為我們要測試的是「未登入」狀態,所以測試的地方要改某一行讓它pass
expect(compiled.querySelector('p').textContent).not.toContain(app.user.name)
因為未登入,就不會取得user.name
<!-- 已登入 -->
<div *ngIf="isLoggedIn">
<h1>User logged in</h1>
<p>User is: {{ user.name }}</p>
</div>
<!-- 未登入 -->
<div *ngIf="!isLoggedIn">
<h1>User not logged in</h1>
<p>Please log in first</p>
</div>
認識如何取得service和調用service裡面的參數,以及要測試正面和反面的情境,各自寫一個test case,對於測試和實做有大大幫助,最後在斷言庫的地方,還好有測試反面情境,認識了可以加 not
的方法,多學了一種使用方式。
下一篇,要來學習「Async」和「fakeAsync」